package com.ht.modules.customerfirminfo.utils;

import com.ht.modules.customerfirminfo.entity.CustomerFirmInfo;
import com.ht.utils.RedisUtil;
import org.apache.logging.log4j.util.Strings;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.net.InetAddress;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 客户企业信息爬虫工具
 */
@Component
public class CustomerFirmInfoCrawlerUtil {
    @Autowired
    private RedisUtil redisUtil;
    // 防止产生验证5S之后才能再次请求
    private static final long EXPIRE_TIME = 5 * 1000;
    private static final String BASE_URL = "https://www.11315.com/";
    private static final String NEW_SEARCH_INTERFACE = "newsearch";
    private static final String NEW_SEARCH_INTERFACE_DETAILS = "new_search_interface_details";

    /**
     * 查询企业信息
     *
     * @param customerFirmInfo 参数
     * @return 查询结果
     */
    public List<CustomerFirmInfo> searchEnterpriseInfo(CustomerFirmInfo customerFirmInfo) {
        try {
            String ip = InetAddress.getLocalHost().getHostAddress();
            String companyName = customerFirmInfo.getCompanyName();
            // 校验一个账号不能调用太频繁不然容易封IP或产生校验
            String redisKey = NEW_SEARCH_INTERFACE + ":" + ip;
            if (redisUtil.hasKey(redisKey)) {
                long expire = redisUtil.getExpire(redisKey);
                throw new RuntimeException("同步太频繁请" + expire + "秒后重试...");
            }
            redisUtil.set(NEW_SEARCH_INTERFACE + ":" + ip, companyName, EXPIRE_TIME / 1000);
            // 简介网址
            String introUrl = BASE_URL + NEW_SEARCH_INTERFACE + "?name=" + companyName;
            Connection.Response response = Jsoup.connect(introUrl)
                    .method(Connection.Method.GET)
                    .timeout(10 * 1000)
                    .execute();
            int statusCode = response.statusCode();
            if (200 != statusCode) {
                throw new RuntimeException(response.statusMessage());
            }
            Elements introElements = response.parse().getElementsByClass("s_c_content fl");
            if (introElements.isEmpty()) {
                return new ArrayList<>();
            }
            return introElements.stream().map(item -> {
                Elements ulLiElements = item.select("ul li");
                Elements h2A = item.select("h2 a");
                CustomerFirmInfo info = new CustomerFirmInfo()
                        .setCompanyName(h2A.get(0).text())
                        .setCreditWebsite(h2A.get(0).attr("href"));
                if (ulLiElements.size() == 3) {
                    info.setCompanyNameHis(ulLiElements.get(0).text())
                            .setLegalRepresentative(ulLiElements.get(1).select("span").get(0).text())
                            .setRegisteredCapital(ulLiElements.get(1).select("span").get(1).text())
                            .setDateOfEstablishment(ulLiElements.get(1).select("span").get(2).text())
                            .setRegisteredAddress(ulLiElements.get(2).text());
                } else {
                    info.setLegalRepresentative(ulLiElements.get(0).select("span").get(0).text())
                            .setRegisteredCapital(ulLiElements.get(0).select("span").get(1).text())
                            .setDateOfEstablishment(ulLiElements.get(0).select("span").get(2).text())
                            .setRegisteredAddress(ulLiElements.get(1).text());
                }
                return info;
            }).collect(Collectors.toList());
        } catch (SocketTimeoutException e) {
            throw new RuntimeException("获取第三方企业信息超时请稍候再试...");
        } catch (Exception e) {
            throw new RuntimeException("获取第三方企业信息异常请联系管理员处理..." + e.getMessage());
        }
    }

    /**
     * 爬取填充客户企业信息
     *
     * @param customerFirmInfo 客户企业信息
     * @return 客户企业信息
     */
    public CustomerFirmInfo crawlerByCompanyName(CustomerFirmInfo customerFirmInfo) {
        String companyName = customerFirmInfo.getCompanyName();
        // 校验一个账号不能调用太频繁不然容易封IP或产生校验
        String redisKey = NEW_SEARCH_INTERFACE_DETAILS;
        if (redisUtil.hasKey(redisKey)) {
            long expire = redisUtil.getExpire(redisKey);
            throw new RuntimeException("同步太频繁请" + expire + "秒后重试...");
        }
        try {
            redisUtil.set(NEW_SEARCH_INTERFACE_DETAILS, companyName, EXPIRE_TIME / 1000);
            // 信用网址
            Connection.Response response = Jsoup.connect(customerFirmInfo.getCreditWebsite())
                    .method(Connection.Method.GET)
                    .timeout(10 * 1000)
                    .execute();
            int statusCode = response.statusCode();
            if (200 != statusCode) {
                throw new RuntimeException(response.statusMessage());
            }
            Elements detailsElements = response.parse().getElementsByClass("v1Table01");
            Elements elements = detailsElements.select("tbody tr");
            Element element = elements.get(1).select("td").get(1);
            // 处理过滤混杂标签
            Elements comShow15 = element.getElementsByClass("comshow_15");
            String registrationNumber = element.text();
            int size = comShow15.size();
            if (size > 0) {
                for (Element element1 : comShow15) {
                    registrationNumber = registrationNumber.replace(element1.text(), "");
                }
            }
            // 组装爬取信息
            // 法定代表人特殊处理
            String legalRepresentative = customerFirmInfo.getLegalRepresentative();

            if (Strings.isBlank(legalRepresentative)) {
                customerFirmInfo.setLegalRepresentative(elements.get(2).select("td").get(0).select("img").attr("src"));
            }
            customerFirmInfo.setUnifyTheSocialCreditCode(elements.get(1).select("td").get(0).text())
                    .setRegistrationNumber(registrationNumber)
                    .setRegisteredCapital(elements.get(2).select("td").get(1).text())
                    .setDateOfEstablishment(elements.get(3).select("td").get(0).text())
                    .setBusinessStatus(elements.get(3).select("td").get(1).text())
                    .setDateOfApproval(elements.get(4).select("td").get(0).text())
                    .setRegistrationAuthority(elements.get(4).select("td").get(1).text())
                    .setOperatingTermFrom(elements.get(5).select("td").get(0).text())
                    .setOpenUntil(elements.get(5).select("td").get(1).text());
            // 企业有历史曾用名的话结构会变化，需要特殊处理
            String registeredAddress;
            String mainProduct;
            String companyProfile;
            if (elements.size() > 9) {
                customerFirmInfo.setCompanyNameHis(elements.get(6).select("td").get(0).text());
                registeredAddress = (elements.get(7).select("td").get(0).text());
                mainProduct = elements.get(8).select("td").get(0).select("span").attr("title");
                companyProfile = elements.get(9).select("td").get(0).select("a").attr("href");
            } else {
                registeredAddress = (elements.get(6).select("td").get(0).text());
                mainProduct = elements.get(7).select("td").get(0).select("span").attr("title");
                companyProfile = elements.get(8).select("td").get(0).select("a").attr("href");
            }
            customerFirmInfo
                    .setRegisteredAddress(registeredAddress)
                    .setMainProduct(mainProduct)
                    .setCompanyProfile(companyProfile);
            // 企业地址为空回填采集到的地址
            String companyAddress = customerFirmInfo.getCompanyAddress();
            if (Strings.isBlank(companyAddress)) {
                customerFirmInfo.setCompanyAddress(registeredAddress);
            }
            customerFirmInfo.setSynchronizedDate(new Date());
            // 联系人为空时使用同步信息
            if (Strings.isBlank(customerFirmInfo.getContactPerson())) {
                customerFirmInfo.setContactPerson(customerFirmInfo.getLegalRepresentative());
            }
            return customerFirmInfo;
        } catch (SocketTimeoutException e) {
            throw new RuntimeException("获取第三方企业信息超时请稍候再试...");
        } catch (Exception e) {
            throw new RuntimeException("获取第三方企业信息异常请联系管理员处理..." + e.getMessage());
        }
    }
}


